fix(distill): detach bg pipeline with setsid so it survives session teardown#322
Merged
Conversation
…eardown
The distill bg pipeline was spawned as a disowned subshell, which stays in
the hook's process group/session. When the parent Claude session is torn
down as a group (ssh-driven maintenance sessions, CLI teardown), the
pipeline is killed before it can log anything — observed fleet-wide on
2026-07-07: gwakga/nosuk sessionend runs ended at "spawned bg" with no
done/skip/error line and stale distill-last.json. disown/nohup only guard
against SIGHUP, not group-targeted kills.
Fix: extract the pipeline body into run_bg_pipeline() and re-invoke the
script via `setsid bash distill.sh` with CLAUDE_DISTILL_BG=1 (new session,
immune to group teardown). Where setsid is unavailable, fall back to the
legacy disowned subshell. Inputs flow through the existing CLAUDE_DISTILL_*
env contract in both modes; the bg re-entry is checked before any hook-input
parsing and does not set INFLIGHT itself, so the recursion guard still
protects the nested `claude -p` session.
Evidence:
- claude/hooks/distill-scope.test.sh: 18/18 PASS
- PG-kill simulation: spawn hook via setsid, `kill -KILL -$$` immediately
after hook exit while stub extract sleeps 2s -> pipeline completes
("dry-run skipping ... elapsed_s=2"). Same scenario reproduced the
silent death with the old spawn.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
seoseo-ai
approved these changes
Jul 7, 2026
seoseo-ai
left a comment
Collaborator
There was a problem hiding this comment.
LGTM — distill bg pipeline setsid detach. Evidence: distill-scope.test.sh 18/18 PASS + PG-kill simulation survival (pipeline completes while parent group SIGKILLed mid-extract). Recursion-guard ordering (BG re-entry before INFLIGHT self-export) verified in review.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
distill.sh의 bg 파이프라인 spawn을 disowned subshell →
setsidself re-entry(신규 세션)로 교체. setsid 미가용 환경은 기존 subshell fallback 유지.Why
2026-07-07 fleet 점검에서 gwakga/nosuk의 sessionend distill이
spawned bg로그 후 done/skip/error 없이 무로그 사망 (distill-last.json stale). 원인: ssh 유지보수 세션 teardown이 프로세스 그룹째 kill → disown/nohup은 SIGHUP만 방어, group-kill 미방어.How
run_bg_pipeline()로 추출 (CLAUDE_DISTILL_* env 계약은 기존과 동일)CLAUDE_DISTILL_BG=1 setsid bash distill.sh <trigger>로 재진입 — 재진입 체크는 hook-input 파싱 이전, INFLIGHT는 파이프라인이 스스로 export하므로 recursion guard 유지mode=setsid|subshell추가 (기존spawned bggrep 계약 유지)Evidence
claude/hooks/distill-scope.test.sh: 18/18 PASSkill -KILL -$$(stub extract sleep 2s 중) → 파이프라인 완주(dry-run skipping ... elapsed_s=2). 구 코드 시나리오 재현으로 silent death 확인됨.Wiki: LOG-1509 후속 (memory-pipeline fleet 점검)
🤖 Generated with Claude Code